﻿using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
using System.IO.Compression;
using System.Windows;
using System.Windows.Media.Imaging;
using Microsoft.Win32;
using QrCode.FountainUtils;

namespace QrCode
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent(); 
        }

        private string zipFilePath = string.Empty;
        private void Select_Click(object sender, RoutedEventArgs e)
        {
            OpenFileDialog openFileDialog = new OpenFileDialog();
            openFileDialog.Multiselect = true; // 允许选择多个文件
            openFileDialog.Filter = "所有文件 (*.*)|*.*"; // 设置文件过滤器，根据需要调整
            var res = openFileDialog.ShowDialog();
            if (res.Value)
            {
                zipFilePath = openFileDialog.FileName;
                txtFilePath.Dispatcher.Invoke(() =>
                {
                    txtFilePath.Text = System.IO.Path.GetDirectoryName(openFileDialog.FileName);
                });
            }
        }

        private void Build_Click(object sender, RoutedEventArgs e)
        {
            // 10M = 10485760 bytes
            //var fileSize = 10 * 1024 * 1024; // 设置文件大小为10MB
            // 读取zip文件到byte数组                                          
            byte[] zipFileBytes = File.ReadAllBytes(zipFilePath);
            // 读取文件并压缩为字节数组
            byte[] compressedBytes = Compress(zipFileBytes);
            // byte转base64
            string base64Content = Convert.ToBase64String(compressedBytes);

            #region 图像哈希 作者：高玩梁 https://www.bilibili.com/read/cv38452107/ 出处：bilibili
            // Cimbar 的核心基于图像哈希技术。图像哈希是一种将图片内容转换为固定长度哈希值的方法。在 Cimbar 中，图像哈希通过简单的阈值算法实现：如果像素被设置为黑色，则为 1，否则为 0。
            // 这种 8x8 的网格最终被编码为 64 位的数字，从左至右、从上至下读取。尽管这种方法并不复杂，但是很简单

            #endregion

            #region Fountain 编码（喷泉码）

            int blockSize = 3;

            FountainCode fountainCode = new FountainCode();

            // 数据分块测试
            List<DataPacket> originalBlocks = fountainCode.SplitData(zipFileBytes, blockSize);
            Console.WriteLine("Original Blocks:");
            foreach (var block in originalBlocks)
            {
                Console.WriteLine(BitConverter.ToString(block.Data));
            }

            // 编码生成测试
            List<DataPacket> encodedBlocks = fountainCode.Encode(originalBlocks);
            Console.WriteLine("Encoded Blocks:");
            for (int i = 0; i < encodedBlocks.Count && i < 10; i++) // 只显示前几个编码块以避免过多输出
            {
                Console.WriteLine(BitConverter.ToString(encodedBlocks[i].Data));
            }

            // 解码测试
            List<DataPacket> decodedBlocks = fountainCode.Decode(encodedBlocks, originalBlocks.Count);
            Console.WriteLine("Decoded Blocks:");
            foreach (var block in decodedBlocks)
            {
                Console.WriteLine(BitConverter.ToString(block.Data));
            }

            // 验证解码结果是否与原始数据块一致
            bool isDecodingSuccessful = true;
            for (int i = 0; i < originalBlocks.Count; i++)
            {
                if (!Enumerable.SequenceEqual(originalBlocks[i].Data, decodedBlocks[i].Data))
                {
                    isDecodingSuccessful = false;
                    break;
                }
            }

            if (isDecodingSuccessful)
            {
                Console.WriteLine("Decoding successful!");
            }
            else
            {
                Console.WriteLine("Decoding failed.");
            }
            #endregion

            #region 其他



            //Bitmap bitmap = new Bitmap(1024, 1024); // 创建一个空白图像

            // 创建喷泉编码器
            //FountainCode fountainCode = new FountainCode(zipFileBytes, blockSize);

            // 生成编码块
            //List<byte[]> encodedBlocks = new List<byte[]>();
            //for (int i = 0; i < blockSize; i++) // 生成编码块
            //{
            //    byte[] encodedBlock = fountainCode.GenerateEncoding();
            //    encodedBlocks.Add(encodedBlock);
            //    Console.WriteLine($"Encoded Block {i + 1}: {BitConverter.ToString(encodedBlock)}");
            //}


            //using (Graphics g = Graphics.FromImage(bitmap))
            //{
            //    // 在这里绘制喷泉码的图形
            //    g.Clear(System.Drawing.Color.White);
            //    // 绘制一个圆形代表水滴
            //    g.FillEllipse(System.Drawing.Brushes.Blue, 50, 50, 100, 100);
            //}

            //dynamicImage.Source = BitmapToImageSource(qrImage);
            #endregion
        }

        #region 其他辅助办法


        /// <summary>
        /// 压缩字节数组
        /// </summary>
        /// <param name="data"></param>
        /// <returns></returns>
        private byte[] Compress(byte[] data)
        {
            using (var compressedStream = new MemoryStream())
            {
                using (var gzipStream = new GZipStream(compressedStream, CompressionMode.Compress))
                {
                    gzipStream.Write(data, 0, data.Length);
                }
                return compressedStream.ToArray();
            }
        }

        private BitmapImage BitmapToImageSource(Bitmap bitmap)
        {
            using (var memory = new MemoryStream())
            {
                //这里需要将原来的bitmap重新复制一份出来使用newBitmap进行Save 否则会报GDI+中出现一般性错误
                //https://stackoverflow.com/questions/15862810/a-generic-error-occurred-in-gdi-in-bitmap-save-method
                Bitmap newBitmap = new Bitmap(bitmap);
                bitmap.Dispose();
                bitmap = null;

                newBitmap.Save(memory, System.Drawing.Imaging.ImageFormat.Bmp);
                memory.Position = 0;
                BitmapImage bitmapImage = new BitmapImage();
                bitmapImage.BeginInit();
                bitmapImage.StreamSource = memory;
                bitmapImage.CacheOption = BitmapCacheOption.OnLoad;
                bitmapImage.EndInit();

                return bitmapImage;
            }
        }

        /**
   　　* 将bitmap转换成base64字符串     　　
   　　* @param bitmap
   　　* @return base64 字符串
   　　*/
        public string BitmapToString(Bitmap bitmap)
        {
            using (var memoryStream = new MemoryStream())
            {
                bitmap.Save(memoryStream, ImageFormat.Jpeg);
                byte[] byteImage = memoryStream.ToArray();
                // Get Base64
                return Convert.ToBase64String(byteImage);
            }
        }

        /**
     　　* 将base64转换成bitmap图片     　　
     　　* @param string base64字符串
     　　* @return bitmap
 　　   */
        public Bitmap StringToBitmap(string base64String)
        {
            Bitmap bmpReturn = null;
            //Convert Base64 string to byte[]
            byte[] byteBuffer = Convert.FromBase64String(base64String);
            using (var memoryStream = new MemoryStream(byteBuffer))
            {
                memoryStream.Position = 0;
                bmpReturn = (Bitmap)Bitmap.FromStream(memoryStream);
                return bmpReturn;
            }
        }

        #endregion

        #region 3. Fountain编码解码

        #endregion
    }
}
